package effective;

import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

enum Operation {
  PLUS("+") {
    @Override
    public double apply(double x, double y) {
      return x + y;
    }
  },
  MINUS("-") {
    @Override
    public double apply(double x, double y) {
      return x - y;
    }
  },
  Times("*") {
    @Override
    public double apply(double x, double y) {
      return x * y;
    }
  },
  DIVID("/") {
    @Override
    public double apply(double x, double y) {
      return x / y;
    }
  };

  private String name;
  Operation(String n) {
    name = n;
    indicator2.setConstructMessage("init " + n);
    // Cannot refer to the static enum field Operation.nameMap2 within an initializer
    // Java(33555194)
    // if (nameMap2 != null) {
    //   nameMap2.put(n, this);
    // }
  }
  @Override 
  public String toString() {
    return name;
  }
  abstract public double apply(double x, double y);
  private static Indicator indicator = new Indicator("static");
  private Indicator indicator2 = new Indicator("local");
  static {
    indicator.setStaticMessage("static init");
  } 
  private static Map<String, Operation> nameMap = Stream.of(values())
            .collect(Collectors.toMap(Object::toString, t->t));

  // private static Map<String, Operation> nameMap2 = new HashMap<>();
  public static Optional<Operation> fromString(String sym) {
    return Optional.ofNullable(nameMap.get(sym));
  }

  static public String getIndicatorMessage() {
    return Stream.of(values())
          .map(t-> t.indicator2).reduce(
            new Indicator("merged"),
            (x, y) -> x.mergeOther(y)
        ).mergeOther(indicator)
          .toString();
  }
}